cpumap cleanups -- Python now deals with lists of cpus
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Sat, 22 Oct 2005 07:35:03 +0000 (08:35 +0100)
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Sat, 22 Oct 2005 07:35:03 +0000 (08:35 +0100)
rather than cpu bitmaps.
Signed-off-by: Ryan Harper <ryanh@us.ibm.com>
Signed-off-by: Keir Fraser <keir@xensource.com>
tools/python/xen/lowlevel/xc/xc.c
tools/python/xen/xend/XendClient.py
tools/python/xen/xend/XendDomain.py
tools/python/xen/xend/XendDomainInfo.py
tools/python/xen/xend/server/SrvDomain.py
tools/python/xen/xm/main.py

index e4855158b615cc163e9dadf26c63e8c1bf4318e5..e3c2dbcb3621c6c67e4267ae99a756de075fa485 100644 (file)
@@ -204,15 +204,23 @@ static PyObject *pyxc_domain_pincpu(PyObject *self,
     XcObject *xc = (XcObject *)self;
 
     uint32_t dom;
-    int vcpu = 0;
+    int vcpu = 0, i;
     cpumap_t cpumap = ~0ULL;
+    PyObject *cpulist = NULL;
 
     static char *kwd_list[] = { "dom", "vcpu", "cpumap", NULL };
 
-    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|ii", kwd_list, 
-                                      &dom, &vcpu, &cpumap) )
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|iO", kwd_list, 
+                                      &dom, &vcpu, &cpulist) )
         return NULL;
 
+    if ( (cpulist != NULL) && PyList_Check(cpulist) )
+    {
+        cpumap = 0ULL;
+        for ( i = 0; i < PyList_Size(cpulist); i++ ) 
+            cpumap |= (cpumap_t)1 << PyInt_AsLong(PyList_GetItem(cpulist, i));
+    }
+  
     if ( xc_domain_pincpu(xc->xc_handle, dom, vcpu, cpumap) != 0 )
         return PyErr_SetFromErrno(xc_error);
     
@@ -347,11 +355,12 @@ static PyObject *pyxc_vcpu_getinfo(PyObject *self,
                                    PyObject *kwds)
 {
     XcObject *xc = (XcObject *)self;
-    PyObject *info_dict;
+    PyObject *info_dict, *cpulist;
 
     uint32_t dom, vcpu = 0;
     xc_vcpuinfo_t info;
-    int rc;
+    int rc, i;
+    cpumap_t cpumap;
 
     static char *kwd_list[] = { "dom", "vcpu", NULL };
     
@@ -363,13 +372,22 @@ static PyObject *pyxc_vcpu_getinfo(PyObject *self,
     if ( rc < 0 )
         return PyErr_SetFromErrno(xc_error);
 
-    info_dict = Py_BuildValue("{s:i,s:i,s:i,s:L,s:i,s:i}",
+    info_dict = Py_BuildValue("{s:i,s:i,s:i,s:L,s:i}",
                               "online",   info.online,
                               "blocked",  info.blocked,
                               "running",  info.running,
                               "cpu_time", info.cpu_time,
-                              "cpu",      info.cpu,
-                              "cpumap",   info.cpumap);
+                              "cpu",      info.cpu);
+
+    cpumap = info.cpumap;
+    cpulist = PyList_New(0);
+    for ( i = 0; cpumap != 0; i++ )
+    {
+        if ( cpumap & 1 )
+            PyList_Append(cpulist, PyInt_FromLong(i));
+        cpumap >>= 1;
+    }
+    PyDict_SetItemString(info_dict, "cpumap", cpulist);
 
     return info_dict;
 }
@@ -896,7 +914,7 @@ static PyMethodDef pyxc_methods[] = {
       "Pin a VCPU to a specified set CPUs.\n"
       " dom [int]:     Identifier of domain to which VCPU belongs.\n"
       " vcpu [int, 0]: VCPU being pinned.\n"
-      " cpumap [int, -1]: Bitmap of usable CPUs.\n\n"
+      " cpumap [list, []]: list of usable CPUs.\n\n"
       "Returns: [int] 0 on success; -1 on error.\n" },
 
     { "domain_setcpuweight", 
index 9fe93bab991ae658f207ab7948ba0378f3d82929..9cbef2401b7ed91153ae73ec076507c471f34836 100644 (file)
@@ -258,7 +258,7 @@ class Xend:
         return self.xendPost(self.domainurl(id),
                              {'op'      : 'pincpu',
                               'vcpu'    : vcpu,
-                              'cpumap'  : cpumap })
+                              'cpumap'  : str(cpumap) })
 
     def xend_domain_cpu_bvt_set(self, id, mcuadv, warpback, warpvalue, warpl, warpu):
         return self.xendPost(self.domainurl(id),
index 0b50c83b5595e5ce019fd7c8493600bd859d2927..3c0532645c28b9fb7099b98384ca48ad380ef3ad 100644 (file)
@@ -412,9 +412,12 @@ class XendDomain:
     def domain_pincpu(self, domid, vcpu, cpumap):
         """Set which cpus vcpu can use
 
-        @param cpumap:  bitmap of usable cpus
+        @param cpumap:  string repr of list of usable cpus
         """
         dominfo = self.domain_lookup(domid)
+        # convert cpumap string into a list of ints
+        cpumap = map(lambda x: int(x),
+                     cpumap.replace("[", "").replace("]", "").split(","))
         try:
             return xc.domain_pincpu(dominfo.getDomid(), vcpu, cpumap)
         except Exception, ex:
index bb34abd0998d15c8330eca74d467ad5e0a06f314..061e7863d5f6b4159bb60aa81d301fd432097f9f 100644 (file)
@@ -980,6 +980,9 @@ class XendDomainInfo:
 
     def getVCPUInfo(self):
         try:
+            def filter_cpumap(map, max):
+                return filter(lambda x: x >= 0, map[0:max])
+
             # We include the domain name and ID, to help xm.
             sxpr = ['domain',
                     ['domid',      self.domid],
@@ -996,7 +999,8 @@ class XendDomainInfo:
                              ['running',  info['running']],
                              ['cpu_time', info['cpu_time'] / 1e9],
                              ['cpu',      info['cpu']],
-                             ['cpumap',   info['cpumap']]])
+                             ['cpumap',   filter_cpumap(info['cpumap'],
+                                                        self.info['vcpus'])]])
 
             return sxpr
 
index 40ddc819729361b7a8eef248c873d6b3801cfe22..676c5f37caf1bd5f751ed1710f630b0b725226e8 100644 (file)
@@ -89,7 +89,7 @@ class SrvDomain(SrvDir):
         fn = FormFn(self.xd.domain_pincpu,
                     [['dom', 'int'],
                      ['vcpu', 'int'],
-                     ['cpumap', 'int']])
+                     ['cpumap', 'str']])
         val = fn(req.args, {'dom': self.dom.domid})
         return val
 
index 7e35899fc0565e5de8c2059b3b7e82793ebd8766..f9771f6c0af2fa2dd58bc932b021a6c364ae47d0 100644 (file)
@@ -289,6 +289,62 @@ def xm_vcpu_list(args):
         def get_info(n):
             return sxp.child_value(dom, n)
 
+        #
+        # convert a list of integers into a list of pairs indicating
+        # continuous sequences in the list:
+        #
+        # [0,1,2,3]   -> [(0,3)]
+        # [1,2,4,5]   -> [(1,2),(4,5)]
+        # [0]         -> [(0,0)]
+        # [0,1,4,6,7] -> [(0,1),(4,4),(6,7)]
+        #
+        def list_to_rangepairs(cmap):
+            cmap.sort()
+            pairs = []
+            x = y = 0
+            for i in range(0,len(cmap)):
+                try:
+                    if ((cmap[y+1] - cmap[i]) > 1):
+                        pairs.append((cmap[x],cmap[y]))
+                        x = y = i+1
+                    else:
+                        y = y + 1
+                # if we go off the end, then just add x to y
+                except IndexError:
+                    pairs.append((cmap[x],cmap[y]))
+
+            return pairs
+
+        #
+        # Convert pairs to range string, e.g: [(1,2),(3,3),(5,7)] -> 1-2,3,5-7
+        #
+        def format_pairs(pairs):
+            out = ""
+            for f,s in pairs:
+                if (f==s):
+                    out += '%d'%f
+                else:
+                    out += '%d-%d'%(f,s)
+                out += ','
+            # trim trailing ','
+            return out[:-1]
+
+        def format_cpumap(cpumap):
+            def uniq(x):
+               return [ u for u in x if u not in locals()['_[1]'] ]
+
+            from xen.xend.XendClient import server
+            for x in server.xend_node()[1:]:
+                if len(x) > 1 and x[0] == 'nr_cpus':
+                    nr_cpus = int(x[1])
+                    break
+            return format_pairs(
+                          list_to_rangepairs(
+                              map(lambda x: x % nr_cpus, 
+                                  uniq(map(lambda x: int(x), cpumap)) )))
+                
+
         name  =     get_info('name')
         domid = int(get_info('domid'))
 
@@ -299,7 +355,7 @@ def xm_vcpu_list(args):
 
             number   = vinfo('number',   int)
             cpu      = vinfo('cpu',      int)
-            cpumap   = vinfo('cpumap',   int)
+            cpumap   = format_cpumap(vinfo('cpumap', list))
             online   = vinfo('online',   int)
             cpu_time = vinfo('cpu_time', float)
             running  = vinfo('running',  int)
@@ -321,7 +377,7 @@ def xm_vcpu_list(args):
                 s = "--p"
 
             print (
-                "%(name)-32s %(domid)3d  %(number)4d  %(c)3s   %(s)-3s   %(cpu_time)7.1f  0x%(cpumap)x" %
+                "%(name)-32s %(domid)3d  %(number)4d  %(c)3s   %(s)-3s   %(cpu_time)7.1f  %(cpumap)s" %
                 locals())
 
 
@@ -355,7 +411,6 @@ def xm_subcommand(command, args):
 
 def cpu_make_map(cpulist):
     cpus = []
-    cpumap = 0
     for c in cpulist.split(','):
         if c.find('-') != -1:
             (x,y) = c.split('-')
@@ -364,10 +419,7 @@ def cpu_make_map(cpulist):
         else:
             cpus.append(int(c))
     cpus.sort()
-    for c in cpus:
-        cpumap = cpumap | 1<<c
-
-    return cpumap
+    return cpus
 
 def xm_vcpu_pin(args):
     arg_check(args, 3, "vcpu-pin")